package com.zzh.ideas.web.controller;

import com.zzh.ideas.core.common.enums.FileType;
import com.zzh.ideas.web.annotation.annotations.TestAnnotation;
import com.zzh.ideas.web.component.Test;
import com.zzh.ideas.web.model.Person;
import com.zzh.ideas.web.service.TestService;
import com.zzh.ideas.web.service.impl.LocalFileServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import org.springframework.web.util.UrlPathHelper;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * description: <br>
 * createTime: 2019/2/1410:44 <br>
 *
 * @author zzh
 */
@RestController
@Import(Test.class)
public class TestController extends BaseController {

    public static ResourceHandlerRegistry registry;

    @Resource
    public HandlerMapping mapping;

    @Resource
    SimpleUrlHandlerMapping simpleUrlHandlerMapping;

    @Resource
    LocalFileServiceImpl fileService;

    @Resource(name= "testService1")
    TestService testService1;

    @Resource(name= "testService2")
    TestService testService2;

    @Resource
    Test test;

    @RequestMapping(value = "test1", method = RequestMethod.POST)
    public String test1(MultipartFile file) throws Exception {
        return fileService.uploadFile(file, "", FileType.DEFAULT);
    }


    @RequestMapping(value = "test2", method = RequestMethod.POST)
    public String test2(MultipartFile file) throws Exception {
        return fileService.uploadFile1(file, "", FileType.DEFAULT);
    }

    @RequestMapping(value = "test3", method = RequestMethod.POST)
    public String test3(MultipartFile file) throws Exception {
        return fileService.uploadFile2(file, "", FileType.DEFAULT);
    }

    //异常
    @Deprecated
    @RequestMapping(value = "test4", method = RequestMethod.GET)
    public String test4() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//        registry.addResourceHandler("/my/**").addResourceLocations("classpath:/my/");

        UrlPathHelper pathHelper = getDeclaredFieldObj(registry, "pathHelper");
        ContentNegotiationManager contentNegotiationManager = getDeclaredFieldObj(registry, "contentNegotiationManager");
        ServletContext servletContext = getDeclaredFieldObj(registry, "servletContext");
        ApplicationContext applicationContext = getDeclaredFieldObj(registry, "applicationContext");

        String pathPattern = "/my/**";
        ResourceHandlerRegistration resourceHandlerRegistration = new ResourceHandlerRegistration(pathPattern);
        resourceHandlerRegistration.addResourceLocations("classpath:/my/");
        ResourceHttpRequestHandler handler =
                (ResourceHttpRequestHandler) invokeDeclaredMethod(resourceHandlerRegistration, "getRequestHandler",
                new Class[]{}, new Object[]{});
        handler.setUrlPathHelper(pathHelper);
        handler.setContentNegotiationManager(contentNegotiationManager);
        handler.setServletContext(servletContext);
        handler.setApplicationContext(applicationContext);
        System.out.println(simpleUrlHandlerMapping != null);
        LinkedHashMap urlMap = getDeclaredFieldObj(mapping, "urlMap");
        urlMap.put(pathPattern, resourceHandlerRegistration);
        return "Hello World";
    }

    @RequestMapping(value = "test5", method = RequestMethod.GET)
    public String test5() {

        return testService1.test() + testService2.test() + test.test();
    }

    @RequestMapping(value = "test6", method = RequestMethod.GET)
    public String test6(Person person)  {

        return person.getName();
    }

    @TestAnnotation
    @RequestMapping(value = "test7", method = RequestMethod.GET)
    public String test7()  {
        System.out.println("test7");
        return "test7";
    }

    @RequestMapping(value = "test8", method = RequestMethod.GET)
    public String test8()  {
        System.out.println("test8");
        return "test8";
    }

    @RequestMapping(value = "testJson", method = RequestMethod.POST)
    public Map<String, Object> testJson(@RequestBody Map<String, Object> map)  {
        System.out.println(map);
        return map;
    }




    //通过反射修改指定对象的某个域属性的值
    private static void changeAttrValueByReflection(Object obj, String fieldName, Object newAttrValue) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, newAttrValue);
    }

    //反射获取给定对象声明的域属性对象
    private  static <T> T  getDeclaredFieldObj(Object obj, String fieldName) throws IllegalAccessException, NoSuchFieldException {
        return getDeclaredFieldObj(obj.getClass(), obj, fieldName);
    }

    //反射获取给定对象声明的域属性对象
    private  static <T> T  getDeclaredFieldObj(Class clazz, Object obj, String fieldName) throws IllegalAccessException,
            NoSuchFieldException {
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return (T) field.get(obj);
    }

    //反射执行给定对象的某个方法
    private  static Object invokeDeclaredMethod(Object obj, String methodName, Class[] classes, Object[] objects) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = obj.getClass().getDeclaredMethod(methodName, classes);
        method.setAccessible(true);
        return method.invoke(obj, objects);
    }
}
